﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Diagnostics;

namespace Common
{
    /// <summary>
    /// 结构转换辅助类
    /// </summary>
    [DebuggerNonUserCode]
    public static class StructHelper
    {
    
    
        /// <summary>
        /// 将结构体转换成字节数组
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="value"></param>
        /// <returns></returns>
        public static byte[] StructToBytes<T>(this T value)
            where T : struct
        {
            Type type = typeof(T);
            Int32 size = Marshal.SizeOf(type);
            IntPtr ptr = Marshal.AllocHGlobal(size);

            try
            {
                Marshal.StructureToPtr(value, ptr, true);

                byte[] buff = new byte[size];

                Marshal.Copy(ptr, buff, 0, size);

                return buff;
            }
            finally
            {
                Marshal.FreeHGlobal(ptr);
            }
        }

        /// <summary>
        /// 将字节数组转换成结构体
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="buff"></param>
        /// <param name="offset"></param>
        /// <param name="len"></param>
        /// <returns></returns>
        public static T BytesToStruct<T>(this byte[] buff, uint offset = 0, uint len = 0)
            where T : struct
        {
            Type type = typeof(T);
            Int32 size = Marshal.SizeOf(type);

            if (len == 0)
                len = (uint)buff.Length - offset;
            else if ((int)offset + len > buff.Length)
                throw new ArgumentException("buff长度有误");

            if (len != size)
                throw new ArgumentException("数据长度与预期不一致，可能是数据结构不匹配导致");

            IntPtr ptr = Marshal.AllocHGlobal(size);

            try
            {
                Marshal.Copy(buff, (int)offset, ptr, size);
                return (T)Marshal.PtrToStructure(ptr, typeof(T));
            }
            finally
            {
                Marshal.FreeHGlobal(ptr);
            }
        }

      
    }
}
